package com.genia.toolbox.persistence.hibernate.manager;

import java.io.Serializable;
import java.util.List;

import com.genia.toolbox.basics.bean.IterableIterator;
import com.genia.toolbox.persistence.bean.Persistable;
import com.genia.toolbox.persistence.bean.QueryParameters;
import com.genia.toolbox.persistence.criteria.Criteria;
import com.genia.toolbox.persistence.criteria.CriteriaResult;
import com.genia.toolbox.persistence.exception.PersistenceException;

/**
 * The transactional part of {@link HibernatePersistenceManager}. This class
 * will be proxied to allow the transactions to be handled.
 */
public interface IHibernatePersistenceManager {

	/**
	 * This method deletes an object.
	 * 
	 * @param object
	 *            The object to delete
	 * @throws PersistenceException
	 *             when an error occurred.
	 */
	public void delete(final Persistable<? extends Serializable> object)
			throws PersistenceException;

	/**
	 * This method returns the results of a criteria.
	 * 
	 * @param <MAINTYPE>
	 *            the main type of the criteria.
	 * @param criteria
	 *            the criteria that describes the query
	 * @param parameters
	 *            the parameters of this search
	 * @return the list of <code>CriteriaResult</code> that represents the
	 *         result of the query
	 * @throws PersistenceException
	 *             when the is a problem with the persisence layer
	 */
	public <MAINTYPE> List<CriteriaResult<MAINTYPE>> find(
			final Criteria<MAINTYPE> criteria, final QueryParameters parameters)
			throws PersistenceException;

	/**
	 * This method get an persited object given its class and identifier.
	 * 
	 * @param <IDENTIFIER>
	 *            The type of the identifier
	 * @param <TYPE>
	 *            The type of the object to retrieve
	 * @param type
	 *            The class of the object to retrieve
	 * @param identifier
	 *            The identifier of the object to retrieve
	 * @return the object of class <code>type</code> with the identifier
	 *         <code>identifier</code> or <code>null</code> if no such
	 *         object exists
	 */
	public <IDENTIFIER extends Serializable, TYPE extends Persistable<IDENTIFIER>> TYPE get(
			final Class<TYPE> type, final IDENTIFIER identifier);

	/**
	 * This method iterates over the results of a criteria.
	 * 
	 * @param <MAINTYPE>
	 *            the main type of the criteria
	 * @param criteria
	 *            the criteria that describes the query
	 * @param parameters
	 *            the parameters of this search
	 * @return the list of <code>CriteriaResult</code> that represents the
	 *         result of the query
	 * @throws PersistenceException
	 *             when the is a problem with the persisence layer
	 * @see com.genia.toolbox.persistence.basis.manager.AbstractPersistenceManager#iterate(com.genia.toolbox.persistence.criteria.Criteria,
	 *      com.genia.toolbox.persistence.bean.QueryParameters)
	 */
	public <MAINTYPE> IterableIterator<CriteriaResult<MAINTYPE>> iterate(
			final Criteria<MAINTYPE> criteria, final QueryParameters parameters)
			throws PersistenceException;

	/**
	 * This method saves a new object.
	 * 
	 * @param object
	 *            The object to save
	 * @throws PersistenceException
	 *             when an error occurred
	 */
	public void save(final Persistable<? extends Serializable> object)
			throws PersistenceException;

	/**
	 * This method saves a new object or update an already persistent object.
	 * This method should be avoided as much as possible. Finding if an object
	 * is persistent or not is tedious and error prone, unexpected comportment
	 * can arrise.
	 * 
	 * @param object
	 *            The object to save or update
	 * @throws PersistenceException
	 *             if any problems occur during persistence process
	 * @see com.genia.toolbox.persistence.manager.PersistenceManager#saveOrUpdate(com.genia.toolbox.persistence.bean.Persistable)
	 */
	public void saveOrUpdate(Persistable<? extends Serializable> object)
			throws PersistenceException;

	/**
	 * This method updates an object.
	 * 
	 * @param object
	 *            The object to update
	 * @throws PersistenceException
	 *             when an error occurred
	 */
	public void update(final Persistable<? extends Serializable> object)
			throws PersistenceException;

}
